import { loadImage } from '../../utils/ImageUtil';
import { randomUUID } from '../../../../mapUtils/RandomUtil';
import CONST from '../../../../constant/Common';
import ITool from '../ITool';

/**
 * 联络图工具箱
 * @implements {ITool}
 */
class ConnectDiagramTool extends ITool {
  constructor(_top, _impl) {
    super(_top, _impl);
    this.name = 'ConnectDiagramTool';
    this.desc = '联络图工具箱';
    this.colors = CONST.colors;
    this.options = {
      padding: 2, // 地图边距
      leftX: -100, // 左侧排列基准位置
      rightX: 100, // 右侧排列基准位置
      mxInterval: 1, // 母线间隔距离
      cxInterval: 2 // 出线开关间隔距离
    };
  }

  onAdd() {
    super.onAdd();
  }

  onRemove() {
    super.onRemove();
  }

  /**
   * 获取地图对象
   */
  getMap() {
    return this.diagram;
  }

  /**
   * 初始化
   * @param {*} container 联络图容器
   * @param {Object} options 配置项
   */
  init(container, options) {
    if (this.diagram) {
      this.remove();
    }
    this.container = container;
    if (options) {
      Object.keys(this.options).forEach((key) => {
        if (options[key]) {
          this.options[key] = options[key];
        }
      });
    }
  }

  /**
   * 初始化地图
   */
  initMap() {
    return new Promise((resolve) => {
      this.diagram = new SGMap.Map({
        container: this.container,
        style: {
          version: 8,
          name: 'BlankMap',
          sources: {},
          glyphs: 'aegis://fonts/aegis/{fontstack}/{range}.pbf',
          layers: [
            {
              id: 'background',
              type: 'background',
              paint: { 'background-color': '#fffbf6' }
            }
          ]
        },
        zoom: 16,
        center: [0, 0],
        localIdeographFontFamily: 'Microsoft YoHei',
        preserveDrawingBuffer: true
      });
      this.diagram.on('load', () => {
        this.initImages();
        this.initLayers();
        resolve();
      });
    });
  }

  /**
   * 移除联络图
   */
  remove() {
    if(this.diagram) {
      this.diagram.remove();
    }
    this.diagram = null;
  }

  /**
   * 重置地图尺寸
   */
  resize() {
    this.diagram.resize();
    this.fitBounds();
  }

  /**
   * 定位地图
   * @ignore
   */
  fitBounds() {
    let padding = this.options.padding / 100;
    let bounds = turf.bbox(turf.envelope(turf.featureCollection(this.features)));
    bounds = [bounds[0] - padding, bounds[1] - padding, bounds[2] + padding, bounds[3] + padding];
    this.getMap().fitBounds(bounds);
  }

  /**
   * 加载联络图
   * @param {Array} data 电网数据
   */
  async render(data) {
    if (!this.diagram) {
      await this.initMap();
    }
    this.data = {
      30000000: [], // 变电站
      30500000: [], // 站内-断路器（出线开关）
      31100000: [], // 站内-母线
      10000100: [], // 大馈线
      10100000: [], // 导线段（连接母线和出线开关）
      32400000: [] // 环网柜
    };
    this.features = [];
    this.loadData(data);
    this.placeBdz();
    this.placeDkx();
    this.setData(this.features);
  }

  /**
   * 解析数据
   * @param {Array} list 电网数据
   * @ignore
   */
  loadData(list) {
    // 数据分类整理
    list.forEach((item) => {
      let sblx = Number(item.sblx);
      if ([30000000, 30500000, 31100000, 10000100, 10100000, 32400000].indexOf(sblx) !== -1) {
        this.data[sblx].push(item);
      } else {
        console.log('未解析:' + sblx);
      }
    });
    // 处理母线和变电站关联关系
    this.data[31100000].forEach((mx) => {
      let bdz = this.data[30000000].find((k) => k.oid === mx.ssdz);
      if (bdz.mx) {
        bdz.mx.push(mx);
      } else {
        bdz.mx = [mx];
      }
    });
    // 处理出线开关和母线关联关系、出线开关和大馈线关联关系
    this.data[30500000].forEach((cxkg) => {
      let ssxl = cxkg.ssxl.split('_')[1];
      let dkx = this.data[10000100].find((k) => k.oid === ssxl);
      dkx.start = cxkg;
      let mx = this.data[31100000].find((k) => k.oid === cxkg.ssmx);
      if (mx.cxkg) {
        mx.cxkg.push(cxkg);
      } else {
        mx.cxkg = [cxkg];
      }
    });
    // 处理环网柜和大馈线关联关系
    this.data[32400000].forEach((hwg) => {
      hwg.icon = 'hw_default';
      this.data[10100000].forEach((line) => {
        if (line.zdsb === hwg.oid) {
          let ssxl = line.ssxl.split('_')[1];
          let dkx = this.data[10000100].find((k) => k.oid === ssxl);
          if (dkx.connections) {
            dkx.connections.push(hwg);
          } else {
            dkx.connections = [hwg];
          }
        }
      });
    });
    // 处理大馈线上的环网柜的排列顺序
    this.data[10000100].forEach((dkx) => {
      if (dkx.connections && dkx.connections.length > 0) {
        let lines = [], path = [], device = null, connectedDevices = [].concat(dkx.connections),
          connectedLines = [].concat(this.data[10100000]);
        // 找出设备连接顺序
        while (connectedDevices.length > 0) {
          let start = dkx.start.oid;
          // 根据起点设备找到连接线
          let lineIndex = connectedLines.findIndex((k) => k.qdsb === start);
          let line = connectedLines[lineIndex];
          connectedLines.splice(lineIndex, 1);
          if (line) {
            // 如果连接线存在，则找到连接线末端连接设备，存入大馈线路径中
            let index = connectedDevices.findIndex((k) => k.oid === line.zdsb);
            device = connectedDevices[index];
            start = device.oid;
            path.push(device);
            connectedDevices.splice(index, 1);
          } else if (start !== dkx.start.oid) {
            // 如果连接线不存在，则大馈线存在分叉情况
            // 如果起始设备不是出线开关，则一个分叉已经排序完成，将起点重置为出线开关，开始排列下一个分叉
            lines.push(path);
            path = [];
            start = dkx.start.oid;
          } else {
            // 如果起始设备是出线开关，则存在错误，清空连接设备结束循环
            connectedDevices = [];
            console.log('设备未找到连接关系:', start);
          }
        }
        if (path.length > 0) {
          lines.push(path);
        }
        dkx.connections = lines;
      }
    });
    console.log(this.data);
  }

  /**
   * 排布变电站
   * @ignore
   */
  placeBdz() {
    let bdzList = this.data[30000000];
    // 统计变电站下的大馈线数
    bdzList.forEach((bdz, index) => {
      bdz.color = this.colors[index];
      bdz.dkxNum = bdz.mx.reduce((total, mx) => {
        return total + mx.cxkg.length;
      }, 0);
    });
    // 根据大馈线数量从大到小排列变电站
    bdzList.sort((a, b) => b.dkxNum - a.dkxNum);
    // 变电站分组规则：
    // 1、变电站分为左右两部分排列
    // 2、比较左右两部分变电站下的大馈线总数，将下一个变电站放入总数较少的一侧
    // 3、当两侧数量一样时，放入左侧开始排列
    let left = [], right = [], leftLength = 0, rightLength = 0, interval = this.options.cxInterval;
    bdzList.forEach((bdz) => {
      if (leftLength <= rightLength) {
        leftLength += (bdz.dkxNum + 2) * interval;
        left.push(bdz);
      } else {
        rightLength += (bdz.dkxNum + 2) * interval;
        right.push(bdz);
      }
    });
    // 变电站及母线排列
    let offset = this.options.mxInterval;
    this.height = Math.max(leftLength, rightLength);
    this.width = this.height * 2;
    let leftX = -this.width / 2, leftY = 0, rightX = this.width / 2, rightY = interval / 2;
    left.forEach((bdz) => {
      let color = bdz.color;
      // 变电站位置
      bdz.coords = [leftX / 100, leftY / 100];
      this.features.push(turf.point(bdz.coords, bdz));
      // 母线位置
      let startY = leftY;
      let endY = startY - (bdz.dkxNum + 1) * interval;
      let offsetNum = (bdz.mx.length - 1) / 2;
      let dkxLabelX = leftX + offsetNum * offset + offset;
      for (let i = 0, j = -offsetNum * offset; i < bdz.mx.length; i++, j = j + offset) {
        let mx = bdz.mx[i];
        let x = leftX + j;
        mx.coords = [[x / 100, startY / 100], [x / 100, endY / 100]];
        this.features.push(turf.lineString(mx.coords, Object.assign({ color: color }, mx)));
        // 母线标注
        this.features.push(turf.point([x / 100, (startY + endY) / 200], {
          sblx: '31100000_text', color: color, sbmc: mx.sbmc, rotate: -90
        }));
        // 出线开关
        // eslint-disable-next-line no-loop-func
        mx.cxkg.forEach((cxkg) => {
          leftY -= interval;
          cxkg.dkxLabelX = dkxLabelX;
          cxkg.color = color;
          cxkg.coords = [x / 100, leftY / 100];
          this.features.push(turf.point(cxkg.coords, Object.assign({ size: 5 }, cxkg)));
        });
      }
      leftY -= interval * 2;
    });
    right.forEach((bdz) => {
      let color = bdz.color;
      // 变电站位置
      bdz.coords = [rightX / 100, rightY / 100];
      this.features.push(turf.point(bdz.coords, bdz));
      // 母线位置
      let startY = rightY;
      let endY = startY - (bdz.dkxNum + 1) * interval;
      let offsetNum = (bdz.mx.length - 1) / 2;
      let dkxLabelX = rightX - offsetNum * offset - offset;
      for (let i = 0, j = -offsetNum * offset; i < bdz.mx.length; i++, j = j + offset) {
        let mx = bdz.mx[i];
        let x = rightX + j;
        mx.coords = [[x / 100, startY / 100], [x / 100, endY / 100]];
        this.features.push(turf.lineString(mx.coords, Object.assign({ color: color }, mx)));
        // 母线标注
        this.features.push(turf.point([x / 100, (startY + endY) / 200], {
          sblx: '31100000_text', color: color, sbmc: mx.sbmc, rotate: 90
        }));
        // 出线开关
        // eslint-disable-next-line no-loop-func
        mx.cxkg.forEach((cxkg) => {
          rightY -= interval;
          cxkg.dkxLabelX = dkxLabelX;
          cxkg.color = color;
          cxkg.coords = [x / 100, rightY / 100];
          this.features.push(turf.point(cxkg.coords, Object.assign({ size: 5 }, cxkg)));
        });
      }
      rightY -= interval * 2;
    });
    console.log(this.features);
  }

  /**
   * 排布大馈线
   * @ignore
   */
  placeDkx() {
    let dkxList = this.data[10000100];
    let baseInterval = this.options.cxInterval, baseX = this.width / 4, leftX = -baseX, rightX = baseX;
    dkxList.forEach((dkx) => {
      let color = dkx.start.color;
      let startCoord = dkx.start.coords;
      // eslint-disable-next-line init-declarations
      let interval, startX, lineX, position;
      if (startCoord[0] < 0) {
        // 左侧
        interval = baseInterval;
        startX = -baseX;
        leftX += baseInterval;
        lineX = leftX;
        position = 'left';
      } else {
        // 右侧
        interval = -baseInterval;
        startX = baseX;
        rightX -= baseInterval;
        lineX = rightX;
        position = 'right';
      }
      if (dkx.connections) {
        // 大馈线末端与联络设备相连
        dkx.coords = [];
        dkx.connections.forEach((path, pathIndex) => {
          let x = lineX;
          let coords = pathIndex === 0 ? [startCoord, [startX / 100, startCoord[1]]] : [[startX / 100, startCoord[1]]];
          path.forEach((lwsb) => {
            if (lwsb.coords) {
              // 联络设备已生成，将末端接到联络设备上
              let lastCoord = coords[coords.length - 1];
              if (pathIndex > 0) {
                coords.push([startX / 100, lwsb.coords[1]], lwsb.coords);
              } else {
                coords.push([lwsb.coords[0], lastCoord[1]], lwsb.coords);
              }
            } else {
              // 联络设备未生成，先生成联络设备，再将末端接到联络设备上
              lwsb.coords = [x / 100, startCoord[1] - baseInterval * pathIndex / 200];
              this.features.push(turf.point(lwsb.coords, Object.assign({ color: '#2a4cae' }, lwsb)));
              if (pathIndex > 0) {
                coords.push([startX / 100, lwsb.coords[1]]);
              }
              coords.push(lwsb.coords);
            }
            x += interval;
          });
          dkx.coords[pathIndex] = coords;
        });
        this.features.push(turf.multiLineString(dkx.coords, Object.assign({ color: color }, dkx)));
      } else {
        // 大馈线末端未连接设备
        dkx.coords = [startCoord, [(startX - interval) / 100, startCoord[1]]];
        this.features.push(turf.lineString(dkx.coords, Object.assign({ color: color }, dkx)));
      }
      // 生成大馈线标注
      this.features.push(turf.point([dkx.start.dkxLabelX / 100, startCoord[1]], {
        sblx: '10000100_text', sbmc: dkx.sbmc, anchor: `top-${position}`, color: color
      }));
    });
  }

  /**
   * 加载渲染数据
   * @param {features} features 图形数据
   * @ignore
   */
  setData(features) {
    this.getMap().getSource(this.sourceId).setData(turf.featureCollection(features));
    this.resize();
  }

  /**
   * 初始化图片
   * @ignore
   */
  initImages() {
    let imageList = [
      { id: 'kg_default', url: 'common/default/KG.png' },
      { id: 'hw_default', url: 'common/default/HW.png' },
      { id: 'df_default', url: 'common/default/DF.png' },
      { id: 'zskg_default', url: 'common/default/ZSKG_0.png' }
    ];
    this.diagram.on('styleimagemissing', (event) => {
      let image = imageList.find((item) => {
        return item.id === event.id;
      });
      if (image) {
        loadImage(this.diagram, image.id, this.getTop().config.get('RESOURCE_BASEURL') + image.url);
      } else if(event.id !== 99) {
        console.log('未在ImageList中找到图片，图片id为:' + event.id);
      }
    });
  }

  /**
   * 初始化图层
   * @ignore
   */
  initLayers() {
    let id = randomUUID();
    let prefix = 'ConnectDiagram';
    this.sourceId = prefix + '_source_' + id;
    this.layerIds = [];
    this.getMap().addSource(this.sourceId, {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: []
      }
    });
    // 变电站图层
    let layerBdzId = prefix + '_layer_bdz_' + id;
    this.layerIds.push(layerBdzId);
    this.getMap().addLayer({
      id: layerBdzId,
      type: 'symbol',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '30000000']],
      layout: {
        'icon-allow-overlap': true,
        'icon-ignore-placement': true,
        'text-field': '{sbmc}',
        'text-size': 16,
        'text-font': ['Microsoft YaHei Regular'],
        'text-offset': [0, -1],
        'text-allow-overlap': true,
        'text-ignore-placement': true,
        'text-optional': true
      },
      paint: {
        'text-color': ['get', 'color']
      }
    });
    // 母线图层
    let layerMxId = prefix + '_layer_mx_' + id;
    this.layerIds.push(layerMxId);
    this.getMap().addLayer({
      id: layerMxId,
      type: 'line',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '31100000']],
      layout: {
        'line-cap': 'round',
        'line-join': 'round'
      },
      paint: {
        'line-color': ['get', 'color'],
        'line-width': ['get', 'width'],
        'line-offset': 0
      }
    });
    // 母线标注图层
    let layerMxTextId = prefix + '_layer_mx_text_' + id;
    this.layerIds.push(layerMxTextId);
    this.getMap().addLayer({
      id: layerMxTextId,
      type: 'symbol',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '31100000_text']],
      layout: {
        'icon-allow-overlap': true,
        'icon-ignore-placement': true,
        'text-field': '{sbmc}',
        'text-size': 12,
        'text-font': ['Microsoft YaHei Regular'],
        'text-offset': [0, -0.7],
        'text-allow-overlap': true,
        'text-ignore-placement': true,
        'text-optional': true,
        'text-rotate': ['get', 'rotate']
      },
      paint: {
        'text-color': ['get', 'color']
      }
    });
    // 出线开关图层
    let layerCxkgId = prefix + '_layer_cxkg_' + id;
    this.layerIds.push(layerCxkgId);
    this.getMap().addLayer({
      id: layerCxkgId,
      type: 'circle',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '30500000']],
      paint: {
        'circle-radius': ['get', 'size'],
        'circle-color': ['get', 'color']
      }
    });
    // 大馈线图层
    let layerDkxId = prefix + '_layer_dkx_' + id;
    this.layerIds.push(layerDkxId);
    this.getMap().addLayer({
      id: layerDkxId,
      type: 'line',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '10000100']],
      layout: {
        'line-cap': 'round',
        'line-join': 'round'
      },
      paint: {
        'line-color': ['get', 'color'],
        'line-width': ['get', 'width'],
        'line-offset': 0
      }
    });
    // 大馈线标注图层
    let layerDkxTextId = prefix + '_layer_dkx_text_' + id;
    this.layerIds.push(layerDkxTextId);
    this.getMap().addLayer({
      id: layerDkxTextId,
      type: 'symbol',
      source: this.sourceId,
      filter: ['all', ['==', 'sblx', '10000100_text']],
      layout: {
        'icon-allow-overlap': true,
        'icon-ignore-placement': true,
        'text-anchor': ['get', 'anchor'],
        'text-field': '{sbmc}',
        'text-size': 12,
        'text-font': ['Microsoft YaHei Regular'],
        'text-offset': [0, -1],
        'text-allow-overlap': true,
        'text-ignore-placement': true,
        'text-optional': true
      },
      paint: {
        'text-color': ['get', 'color']
      }
    });
    // 联络设备图层
    let layerMarkerId = prefix + '_layer_marker_' + id;
    this.layerIds.push(layerMarkerId);
    this.getMap().addLayer({
      id: layerMarkerId,
      type: 'symbol',
      source: this.sourceId,
      filter: ['any', ['==', 'sblx', '32400000']],
      layout: {
        'icon-image': '{icon}',
        'icon-size': ['get', 'iconSize'],
        'icon-allow-overlap': true,
        'icon-ignore-placement': true,
        'icon-anchor': 'center',
        'text-field': '{sbmc}',
        'text-size': 12,
        'text-font': ['Microsoft YaHei Regular'],
        'text-max-width': 8,
        'text-offset': [0, 2],
        'text-allow-overlap': true,
        'text-ignore-placement': true,
        'text-optional': true
      },
      paint: {
        'text-color': ['get', 'color']
      }
    });
  }
}

export default ConnectDiagramTool;